package mymail.sendmail;

import java.io.File;
import java.io.FileOutputStream;
import java.security.Key;
import java.util.ArrayList;
import java.util.Properties;


import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;

import javax.mail.internet.MimeMultipart;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;

import mymail.crypttwice.SymmetricThenRSA;

public class Send {

    /**
     * @param args
     */
    @SuppressWarnings({"static-access", "deprecation"})
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        String data = "My test mail";

        // Pass cho AES phải >= 4 kí tự
        // Pass cho DES và DESede phải có 8 kí tự
        String passwordData = "12345678";
        String algorithm = "DES";

        // String algorithm = "RSAFile";

        final String usernamesender = "anm.hcb.sender2012@gmail.com";
        final String passwordsender = "huongtram";

        final String usernamereceiver = "anm.hcb.receiver201@gmail.com";
        final String passwordreceiver = "huongtram";

        Key privateKey = null;
        Key publicKey = null;

        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.port", "587");

        System.out.println("Loged in with email: " + usernamesender);
        Session session = Session.getInstance(props,
                new javax.mail.Authenticator() {

                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication(usernamesender,
                                passwordsender);
                    }
                });

        try {

            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(usernamesender));
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse(usernamereceiver));
            message.setSubject(algorithm);

            // Text

            String encryptedMessage;

            // encryptedMessage = Cryptography.Encrypt(passwordData,
            // data, algorithm);

            SymmetricThenRSA asymAlgorithm = new SymmetricThenRSA();

            encryptedMessage = asymAlgorithm.Encrypt(passwordData, data, algorithm);
            privateKey = asymAlgorithm.getPrivateKey();

            //message.setText(encryptedMessage);

            // File

            MimeBodyPart messagePart = new MimeBodyPart();
            messagePart.setText(encryptedMessage);

            //
            // Set the email attachment file
            //

            // RSA rsa = new RSA();
//			 String filename = rsa.EncryptFile("D://attachment.txt");
//			 privateKey = rsa.getPrivateKey();
//			 publicKey = rsa.getPublicKey();

            String filename = asymAlgorithm.EncryptFile("D://attachment.txt",
                    passwordData, algorithm);

            File directory = new File(".");
            // Lưu privateKey

            FileOutputStream fos = new FileOutputStream(
                    directory.getCanonicalFile()
                    + "/generatedKeypairs/test.private");

            fos.write(privateKey.getEncoded());
            fos.close();

            System.out.println("Wrote Private key!");
            System.out.println("Private key: " + privateKey);
            //
            // // Lưu publicKey
            //
            // fos = new FileOutputStream(directory.getCanonicalFile()
            // + "/generatedKeypairs/test.public");
            //
            // fos.write(privateKey.getEncoded());
            // fos.close();
            //
            // System.out.println("Wrote Public key!");
            // System.out.println("Public key: " + publicKey);
            //
            // Bảo mật file .private

            ZipFile zipFile = new ZipFile(directory.getCanonicalFile()
                    + "/generatedKeypairs/test.zip");

            ArrayList<File> filesToAdd = new ArrayList<File>();

            File pri = new File(directory.getCanonicalFile()
                    + "/generatedKeypairs/test.private");

            filesToAdd.add(pri);

            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);

            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

            parameters.setEncryptFiles(true);

            parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD);

            parameters.setPassword("test123!");

            zipFile.addFiles(filesToAdd, parameters);
            System.out.println("Zipped Private key!");

            pri.delete();
            System.out.println("Deleted Private key!");

            // Attach file

            MimeBodyPart attachmentPart = new MimeBodyPart();

            FileDataSource fileDataSource = new FileDataSource(filename) {

                @Override
                public String getContentType() {
                    return "text/plain";
                }
            };
            attachmentPart.setDataHandler(new DataHandler(fileDataSource));

            int last = filename.lastIndexOf("/");
            String name = filename.substring(last + 1);

            attachmentPart.setFileName(name);

            Multipart multipart = new MimeMultipart();
            multipart.addBodyPart(messagePart);
            multipart.addBodyPart(attachmentPart);

            message.setContent(multipart);

            System.out.println("Sending!");

            Transport.send(message);

            System.out.println("Sent!");

            // System.out
            // .println("Content Encrypted message: " + encryptedMessage);

            System.out.println();

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }

        System.out.println("Wait 15 seconds!");
        Thread.currentThread().sleep(10000);

        props = System.getProperties();
        props.setProperty("mail.store.protocol", "imaps");
        try {
            session = Session.getDefaultInstance(props, null);
            Store store = session.getStore("imaps");
            store.connect("imap.gmail.com", usernamereceiver, passwordreceiver);

            System.out.println("Loged in with email: " + usernamereceiver);
            System.out.println("Reading Inbox.");
            Folder folder = store.getFolder("INBOX");// get inbox

            folder.open(Folder.READ_ONLY);// open folder only to read

            Message messages[] = folder.getMessages();

            for (Message msg : messages) {

                System.out.println("Subject: " + msg.getSubject());
                System.out.println("Sent date: " + msg.getSentDate());
                System.out.println("Received date: " + msg.getReceivedDate());
                if (Multipart.class.isInstance(msg.getContent())) {
                    Multipart parts = (Multipart) msg.getContent();
                    int i;
                    for (i = 0; i < parts.getCount(); i++) {
                        javax.mail.BodyPart p = parts.getBodyPart(i);

                        if (p.getFileName() == null) {
                            try {

                                // Text

                                String content = (String) p.getContent();

                                String decryptedMessage;

                                // decryptedMessage =
                                // Cryptography.Decrypt(passwordData,
                                // new BASE64Decoder().decodeBuffer((String) p
                                // .getContent()), msg.getSubject());

                                // decryptedMessage = RSA.Decrypt(content,
                                // privateKey);

                                // System.out
                                // .println("Content Decrypted message: "
                                // + decryptedMessage);
                            } catch (Exception ex) {

                                System.out.println("Content Decrypted message: "
                                        + p.getContent());
                            }
                        } else {
                            // // Xử lý các part không phải là text
                            // InputStream stream = p.getInputStream();
                            //
                            // File directory = new File(".");
                            //
                            // String outputFilename = directory
                            // .getCanonicalPath()
                            // + "/temp/"
                            // + msg.getReceivedDate().toLocaleString()
                            // .replace(" ", "").replace(":", "")
                            // + "_" + p.getFileName();
                            // String inputFilename =
                            // directory.getCanonicalPath()
                            // + "/downloads/"
                            // + msg.getReceivedDate().toLocaleString()
                            // .replace(" ", "").replace(":", "")
                            // + "_" + algorithm + "_" + "output.txt";
                            //
                            // File f = new File(outputFilename);
                            // f.createNewFile();
                            //
                            // OutputStream out = new FileOutputStream(
                            // outputFilename);
                            // byte buf[] = new byte[1024];
                            // int len;
                            // while ((len = stream.read(buf)) > 0)
                            // out.write(buf, 0, len);
                            // out.close();
                            // //
                            // byte[] decryptedData = new byte[p.getSize()];
                            //
                            // DataInputStream dis = new
                            // DataInputStream(stream);
                            // int read = 0;
                            // int numRead = 0;
                            // while (read < decryptedData.length
                            // && (numRead = dis.read(decryptedData, read,
                            // decryptedData.length - read)) >= 0) {
                            // read = read + numRead;
                            // }
                            // stream.close();
                            // //
                            // // // Đọc key
                            // //
                            // // ZipFile zipFile = new ZipFile(
                            // // directory.getCanonicalFile()
                            // // + "/generatedKeypairs/test.zip");
                            // //
                            // // if (zipFile.isEncrypted()) {
                            // // zipFile.setPassword("test123!");
                            // // }
                            // //
                            // //
                            // zipFile.extractAll(directory.getCanonicalFile()
                            // // + "/generatedKeypairs/");
                            // //
                            // // System.out.println("Unipped Private key!");
                            // //
                            // // File file = new
                            // File(directory.getCanonicalFile()
                            // // + "/generatedKeypairs/test.private");
                            // // FileInputStream fis = new
                            // FileInputStream(file);
                            // //
                            // // byte[] priBytes = new byte[(int)
                            // file.length()];
                            // // fis.read(priBytes);
                            // // fis.close();
                            // //
                            // // file.delete();
                            // // System.out.println("Deleted Private key!");
                            // //
                            // // KeyFactory keyFactory = KeyFactory
                            // // .getInstance("RSA");
                            // // EncodedKeySpec privateKeySpec = new
                            // // PKCS8EncodedKeySpec(
                            // // priBytes);
                            // // PrivateKey privateKey2 = keyFactory
                            // // .generatePrivate(privateKeySpec);
                            //
                            // // Giải mã
                            // // RSA.DecryptFile(outputFilename, inputFilename,
                            // // privateKey2);
                            //
                            // Cryptography.DecryptFile(outputFilename,
                            // inputFilename, passwordData, algorithm);
                            //
                            // System.out.println("Content type: "
                            // + p.getContentType());
                        }
                    }
                } else {

                    try {

                        // Text

                        File directory = new File(".");

                        ZipFile zipFile = new ZipFile(
                                directory.getCanonicalFile()
                                + "/generatedKeypairs/test.zip");

                        if (zipFile.isEncrypted()) {
                            zipFile.setPassword("test123!");
                        }

                        zipFile.extractAll(directory.getCanonicalFile()
                                + "/generatedKeypairs/");

                        System.out.println("Unipped Private key!");

                        String content = (String) msg.getContent();

                        String decryptedMessage;

                        // decryptedMessage =
                        // Cryptography.Decrypt(passwordData,
                        // new BASE64Decoder().decodeBuffer((String) p
                        // .getContent()), msg.getSubject());

                        // decryptedMessage = RSA.Decrypt(content, privateKey);

                        decryptedMessage = SymmetricThenRSA.Decrypt(
                                passwordData, content, algorithm,
                                directory.getCanonicalFile()
                                + "/generatedKeypairs/test.private");

                        System.out.println("Content Decrypted message: "
                                + decryptedMessage);

                    } catch (Exception ex) {

                        System.out.println("Content Decrypted message: "
                                + msg.getContent());
                    }
                }

            }

        } catch (NoSuchProviderException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (MessagingException e) {
            e.printStackTrace();
            System.exit(2);
        }

        System.out.println("Done");
    }
}
